package com.zhengjiang.purchase.service.impl;

import com.zhengjiang.purchase.model.pojo.PurchaseRecordPO;
import com.zhengjiang.purchase.service.PurchaseService;
import com.zhengjiang.purchase.service.TaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author zhengjiang
 * @version 1.0.0
 * @description 定时任务实现
 * @date 2021/6/20
 **/
@Slf4j
@Service
public class TaskServiceImpl implements TaskService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private PurchaseService purchaseService;

    private static final String PRODUCT_SCHEDULE_SET = "product_schedule_set";
    private static final String PURCHASE_PRODUCT_LIST = "purchase_list_";

    //分批次，每批次1000条
    private static final int ONE_TIME_SIZE = 1000;

    @Scheduled(fixedRate = 1000 * 60) //每分钟执行一次
    @Override
    public void purchaseTask() {
      log.info("定时任务开始......");
        Set<String> productIdList = stringRedisTemplate.opsForSet().members(PRODUCT_SCHEDULE_SET);
        List<PurchaseRecordPO> prpList = new ArrayList<>();
        for (String productIdStr : productIdList){
            Long productId = Long.valueOf(productIdStr);
            String purchaseKey = PURCHASE_PRODUCT_LIST + productId;
            BoundListOperations<String, String> ops = stringRedisTemplate.boundListOps(purchaseKey);
            //计算购买记录数
            long size = stringRedisTemplate.opsForList().size(purchaseKey);
            //计算批次
            long times = size % ONE_TIME_SIZE == 0 ? size / ONE_TIME_SIZE : size / ONE_TIME_SIZE +1;
            for (int i=0;i<times;i++){
                List<String> prList = null;
                if (i == 0){
                    prList = ops.range(i*ONE_TIME_SIZE,(i+1)*ONE_TIME_SIZE);
                }else {
                    prList = ops.range(i*ONE_TIME_SIZE+1,(i+1)*ONE_TIME_SIZE);
                }
                for (String prString : prList){
                    PurchaseRecordPO prp = this.createPurchaseRecord(productId,prString);
                    prpList.add(prp);
                }
                purchaseService.dealRedisPurchase(prpList);
                prList.clear();
            }
            //删除购买列表
            stringRedisTemplate.delete(purchaseKey);
            //从商品集合中删除商品
            stringRedisTemplate.opsForSet().remove(PRODUCT_SCHEDULE_SET,productIdStr);
        }
        log.info("定时任务结束......");
    }

    private PurchaseRecordPO createPurchaseRecord(Long productId, String prString) {
        String arr[] = prString.split(",");
        Long userId = Long.valueOf(arr[0]);
        int quantity = Integer.valueOf(arr[1]);
        double sum = Double.valueOf(arr[2]);
        double price = Double.valueOf(arr[3]);
        Long time = Long.parseLong(arr[4]);
        Timestamp purchaseTime = new Timestamp(time);
        PurchaseRecordPO po = PurchaseRecordPO.builder()
                                .productId(productId)
                                .userId(userId)
                                .quantity(quantity)
                                .sum(sum)
                                .price(price).purchaseTime(purchaseTime)
                                .note("购买日志,时间:" + purchaseTime.getTime())
                                .build();
        return po;
    }
}
